﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Common;
using DevExpress.Data.Filtering;
using DevExpress.Skins;
using DevExpress.LookAndFeel;
using DevExpress.UserSkins;
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
using DevExpress.XtraBars.Ribbon;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using DevExpress.XtraSplashScreen;
using GdPicture;
using Korzh.EasyQuery.Db;
using LicenseManager = GdPicture.LicenseManager;
using Path = System.IO.Path;


namespace DataExporter
{
    public partial class FormExport : XtraForm
    {
        private string _layoutSavePath = @"Kise\Exporter\Layout";

        private string ModelFile
        {
            get { return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LprEasyQuery.xml"); }
        }

        public FormExport()
        {
            _lm = new GdPicture.LicenseManager();
            _lm.RegisterKEY("4118570640491345351491454");
            InitializeComponent();
            // DataExporter.Helper.InitGrid(this.gridControl, this.gridView1);
            InitTileControl();

            dbModel1.LoadFromFile(ModelFile); queryPanel1.Activate();

        }

        private void InitTileControl()
        {
            _gp = new TileGroup();
            // tileControl1.Groups.Add(_gp);
        }

        private void ClearTiles()
        {
            _gp.Items.Clear();
        }

        private TileItem AddTile(Image image, string hphm)
        {
            var item = new TileItem();
            item.Image = image;
            item.ImageScaleMode = TileItemImageScaleMode.Squeeze;
            item.IsLarge = true;
            item.ImageAlignment = TileItemContentAlignment.MiddleCenter;
            _gp.Items.Add(item);

            return item;
        }

        private DateTime _from;
        private DateTime _to;
        private ObservableCollection<Record> _collection;
        private TileGroup _gp;
        private string _subDirectory;
        private string _fileName;
        private LicenseManager _lm;


        private void barButtonItemOptions_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            using (var form = new FormOptions())
            {
                form.ShowDialog(this);
            }
        }


        private async void ExportDataAsyncCore(bool selectFile, Func<IProgress<ExportDataProgress>, Task<Tuple<int, int, int>>> taskToDo)
        {
            if (selectFile)
            {
                var fileName = DataExporter.Helper.GetSaveFileName();
                if (string.IsNullOrEmpty(fileName)) return;

                _fileName = fileName;
            }
            else
            {
                var dlg = new FolderBrowserDialog();
                if (dlg.ShowDialog(this) != DialogResult.OK)
                {
                    return;
                }

                var dirName = DateTime.Now.ToString("yy年MM月dd日 HH点mm分 图片");

                var dir = Path.Combine(dlg.SelectedPath, dirName);
                Directory.CreateDirectory(dir);
                _dirName = dir;
            }

            SplashScreenManager.ShowForm(typeof(WaitForm2));

            var progress = new Progress<ExportDataProgress>();
            progress.ProgressChanged += (s, args) => SplashScreenManager.Default.SendCommand(WaitForm2.WaitFormCommand.UpdateProgress, args);


            try
            {
                var count = await taskToDo(progress);
                SplashScreenManager.CloseForm(false);
                var msg = string.Format("总计导出 {0} 条记录, 其中 {1} 条记录导出成功, {2} 条记录导出失败。", count.Item1, count.Item2, count.Item3);
                MessageBox.Show(this, msg, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                SplashScreenManager.CloseForm(false);
                MessageBox.Show(this, "导出数据时发生异常\r\n\r\n" + ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private bool IsDateRangeValid()
        {
            return true;
        }

        private void GetDirectory()
        {
            var dlg = new FolderBrowserDialog();
            if (dlg.ShowDialog(this) == DialogResult.OK)
            {
            }
        }

        private Task<Tuple<int, int, int>> ExportDataAsync(IProgress<ExportDataProgress> progress)
        {
            return TaskEx.Run(() =>
            {
                if (_collection != null)
                {
                    int count = 0;
                    var collection = new List<Record>();
                    foreach (var r in _collection)
                    {
                        try
                        {
                            var td = GetTargetPictureDirectory();
                            CopyImage(td, r.TxUrl, r.ImageRelativePath1);
                            CopyImage(td, r.TxUrl, r.ImageRelativePath2);
                            CopyImage(td, r.TxUrl, r.ImageRelativePath3);
                            collection.Add(r);
                        }
                        catch (Exception ex)
                        {
                            if (HandleException(ex))
                                throw;
                        }

                        ++count;
                        if (progress != null)
                        {
                            var arg = new ExportDataProgress();
                            arg.Percentage = (int)(((float)count) / _collection.Count * 100);
                            arg.Text = string.Format("{0}/{1}", count, _collection.Count);
                            progress.Report(arg);
                        }
                    }

                    var writer = new FileHelpers.DelimitedFileEngine(typeof(Record));
                    writer.WriteFile(_fileName, collection);
                    return new Tuple<int, int, int>(_collection.Count, collection.Count, _collection.Count - collection.Count);
                }

                return new Tuple<int, int, int>(0, 0, 0);
            });

        }

        private Task<Tuple<int, int, int>> ExportPicturesAsync(IProgress<ExportDataProgress> progress)
        {

            return TaskEx.Run(() =>
                                  {
                                      var dl = DataExporter.Helper.ConnectToDb(
                                          Properties.Settings.Default.DbServer,
                                          Properties.Settings.Default.DbUserName,
                                          Properties.Settings.Default.DbPwd);
                                      var session = new Session(dl);
                                      var xpCursor = new XPCursor(session, typeof(TogVehmon));
                                      var totalCount = xpCursor.Count;
                                      var count = 0;
                                      var failCount = 0;
                                      foreach (TogVehmon r in xpCursor)
                                      {
                                          if (!string.IsNullOrEmpty(r.TXURL)
                                              && Path.IsPathRooted(r.TXURL))
                                          {
                                              r.TXURL = r.TXURL.Substring(1);
                                          }
                                          try
                                          {

                                              CopyImage(_dirName, r.TXURL, r.TXMC1);
                                              CopyImage(_dirName, r.TXURL, r.TXMC2);
                                              CopyImage(_dirName, r.TXURL, r.TXMC3);
                                          }
                                          catch (Exception ex)
                                          {
                                              if (HandleException(ex))
                                                  throw;

                                              failCount++;
                                          }

                                          ++count;

                                          if (progress != null)
                                          {
                                              var arg = new ExportDataProgress();
                                              arg.Percentage = (int)(((float)count) / totalCount * 100);
                                              arg.Text = string.Format("{0}/{1}", count, totalCount);
                                              progress.Report(arg);
                                          }
                                      }

                                      return new Tuple<int, int, int>(totalCount, totalCount - failCount, failCount);

                                  });

        }

        private static bool HandleException(Exception ex)
        {
            var we = ex as WebException;
            return (we != null && we.Status == WebExceptionStatus.ConnectFailure);
        }


        private int _pageIndex = 0;
        private int _pageSize = 50;
        private XPPageSelector _page;
        private string _dirName;

        private void LoadDataAsync(string sql)
        {

            var connectionString = string.Format("Data Source={0};User Id={1};Password={2};",
                                                 Properties.Settings.Default.DbServer,
                                                 Properties.Settings.Default.DbUserName,
                                                 Properties.Settings.Default.DbPwd);
            var adapter = new Devart.Data.Oracle.OracleDataAdapter(sql, connectionString);

            adapter.Fill(dataSet1);
            var count = dataSet1.Tables[0].Rows.Count;
            this.gridControl.DataSource = dataSet1.Tables[0];
            //this.gridControl.DataMember = "result";

        }

        private static Record Vehmon2Record(TogVehmon togVehmon)
        {
            var r = new Record();
            r.CaptureMethod = "2";
            r.CaptureTime = togVehmon.JGSK;
            r.CarType = togVehmon.HPZL;
            r.LprNumber = togVehmon.HPHM == "00000" ? "川R" : togVehmon.HPHM;
            r.RoadNo = togVehmon.KKBH;
            r.ViolationCode = togVehmon.WZYY;
            r.FImageRelativePath1 = togVehmon.TXMC1;
            r.FImageRelativePath2 = togVehmon.TXMC2;
            r.FImageRelativePath3 = togVehmon.TXMC3;
            r.TxUrl = Path.IsPathRooted(togVehmon.TXURL) ? togVehmon.TXURL.Substring(1) : togVehmon.TXURL;

            return r;
        }



        private string CopyImage(string targetDirectory, string imageDir, string imgRelativePath)
        {
            if (!string.IsNullOrEmpty(imgRelativePath))
            {
                var remotePath = Path.Combine(imageDir, imgRelativePath);
                var localDir = targetDirectory;
                var localPath = Path.Combine(localDir, remotePath);

                var parentDir = Path.GetDirectoryName(localPath);
                if (!Directory.Exists(parentDir))
                {
                    Directory.CreateDirectory(parentDir);
                }

                Stream stream = null;
                DownloadFtpFile(remotePath, out stream);
                var fs = File.OpenWrite(localPath);
                stream.CopyTo(fs);
                fs.Close();
                return remotePath;

            }

            return null;

        }

        private string GetTargetPictureDirectory()
        {
            return Path.Combine(Path.GetDirectoryName(_fileName), Path.GetFileNameWithoutExtension(_fileName) + "_图片");
        }


        private void simpleButtonSelectDirectory_Click(object sender, EventArgs e)
        {
            GetDirectory();
            //AddTile()
        }

        private async void simpleButtonLoad_Click(object sender, EventArgs e)
        {
            if (!IsDateRangeValid()) return;

            this.dataSet1.Reset();

            var sql = BuildQuery();


            simpleButtonLoad.Enabled = false;
            splashScreenManager1.ShowWaitForm();
            // progressPanel1.Visible = true;
            this.UseWaitCursor = true;
            Exception exception = null;
            try
            {
                LoadDataAsync(sql);
                //_collection = new ObservableCollection<Record>(col);
                UpdatePageIndicator();
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            this.UseWaitCursor = false;
            //gridControl.DataSource = _collection;
            gridView1.BestFitColumns();
            splashScreenManager1.CloseWaitForm();
            if (exception != null)
            {
                MessageBox.Show("无法查询数据库\r\n\r\n" + exception.Message);
            }

            //progressPanel1.Visible = false;
            simpleButtonLoad.Enabled = true;
        }

        private string BuildQuery()
        {
            var builder = new SqlQueryBuilder(this.dbQuery1);
            if (builder.CanBuild)
            {
                builder.BuildSQL();
                return builder.Result.SQL;
            }

            return null;
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            //layoutControl1.RestoreLayoutFromRegistry(_layoutSavePath);

            var now = DateTime.Now;
            now = now.AddSeconds(-now.Second).AddMilliseconds(-now.Millisecond);

            if (string.IsNullOrEmpty(Properties.Settings.Default.DbServer)
                || string.IsNullOrEmpty(Properties.Settings.Default.FtpServerIp))
            {
                MessageBox.Show("系统第一次运行或者参数不正确，请重新配置系统参数。");
                using (var form = new FormOptions())
                {
                    form.ShowDialog(this);

                }
            }
        }


        private async void gridView1_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            if (e.FocusedRowHandle != -1)
            {
                ClearTiles();
                var record = gridView1.GetRow(e.FocusedRowHandle) as Record;
                if (record != null && !string.IsNullOrEmpty(record.TxUrl))
                {
                    EnableButtons(record);
                    try
                    {
                        this.pictureEditLoadingProgress.Image = pictureEditLoadingProgress.Properties.InitialImage;
                        pictureEditLoadingProgress.Visible = true;

                        var img = await DownloadImageAsync(record.TxUrl, record.ImageRelativePath1);

                        pictureEditLoadingProgress.Visible = false;
                        this.gdViewer1.DisplayFromBitmap((Bitmap)img);
                    }
                    catch (Exception ex)
                    {
                        gdViewer1.CloseDocument();
                        pictureEditLoadingProgress.Image = pictureEditLoadingProgress.Properties.ErrorImage;
                    }
                }
            }
        }

        private void EnableButtons(Record record)
        {
            simpleButtonFirstImage.Enabled = !string.IsNullOrEmpty(record.TxUrl) &&
                                             !string.IsNullOrEmpty(record.ImageRelativePath1);
            simpleButtonSecond.Enabled = !string.IsNullOrEmpty(record.TxUrl) &&
                                             !string.IsNullOrEmpty(record.ImageRelativePath2);
            simpleButtonThird.Enabled = !string.IsNullOrEmpty(record.TxUrl) &&
                                        !string.IsNullOrEmpty(record.ImageRelativePath3);
        }

        private Task<Image> DownloadImageAsync(string txWz, string imageRelativePath1)
        {
            return TaskEx.Run(() =>
                           {
                               if (string.IsNullOrEmpty(txWz) || string.IsNullOrEmpty(imageRelativePath1))
                               {
                                   return null;
                               }
                               var path = Path.Combine(txWz, imageRelativePath1);
                               Stream stream;
                               var response = DownloadFtpFile(path, out stream);
                               var img = Image.FromStream(stream);
                               response.Close();
                               return img;
                           });

        }

        private static WebResponse DownloadFtpFile(string path, out Stream stream)
        {
            var ftpServerUrl = string.Format("http://{0}/", Properties.Settings.Default.FtpServerIp);
            var absUrl = ftpServerUrl + path;
            var ftpClient = System.Net.WebRequest.Create(absUrl);
            ftpClient.Credentials = new NetworkCredential(Properties.Settings.Default.FtpUserName, Properties.Settings.Default.FtpPwd);
            var response = ftpClient.GetResponse();
            stream = response.GetResponseStream();
            return response;
        }




        private TileItem AddTile(string directory, string imgRelativePath, string hphm)
        {
            if (!string.IsNullOrEmpty(imgRelativePath) && !string.IsNullOrEmpty(directory))
            {


                var imgPath = Path.Combine(directory, imgRelativePath);
                if (File.Exists(imgPath))
                {
                    MessageBox.Show("Add tile" + imgPath);
                    var img = Image.FromFile(imgPath);
                    return AddTile(img, hphm);
                }
                else
                {
                    MessageBox.Show(imgPath + " doesn't exist");
                }

            }
            else
            {
                MessageBox.Show("can't add tile");
            }

            return null;

        }




        private async void showImageButtonClick(object sender, EventArgs e)
        {
            var record = gridView1.GetFocusedRow() as Record;
            if (record != null)
            {
                try
                {
                    if (sender.Equals(simpleButtonFirstImage))
                    {
                        var img = await DownloadImageAsync(record.TxUrl, record.ImageRelativePath1);
                        this.gdViewer1.DisplayFromBitmap((Bitmap)img);

                    }
                    else if (sender.Equals(simpleButtonSecond))
                    {
                        var img = await DownloadImageAsync(record.TxUrl, record.ImageRelativePath2);
                        this.gdViewer1.DisplayFromBitmap((Bitmap)img);


                    }
                    else if (sender.Equals(simpleButtonThird))
                    {
                        var img = await DownloadImageAsync(record.TxUrl, record.ImageRelativePath3);
                        this.gdViewer1.DisplayFromBitmap((Bitmap)img);


                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show("下载图片出现错误：" + ex.Message);

                }
            }
        }

        private void iExport_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (HasNextPage())
            {
                if (MessageBox.Show(this, "还有违章数据没有处理完，你确定要导出吗？", this.Text, MessageBoxButtons.OKCancel) != DialogResult.OK)
                {
                    return;
                }
            }

            ExportDataAsyncCore(true, ExportDataAsync);
        }

        private async void barButtonItemOpenFile_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            var fileName = DataExporter.Helper.GetOpenFileName();
            if (string.IsNullOrEmpty(fileName)) return;

            try
            {
                var records = await DataExporter.Helper.ReadFileAsync(fileName);
                _collection = new ObservableCollection<Record>(records);
                // this.gridControl.DataSource = _collection;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }


        }

        private async void barButtonItemSave_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            var fileName = DataExporter.Helper.GetSaveFileName();
            if (string.IsNullOrEmpty(fileName)) return;

            try
            {
                await DataExporter.Helper.WriteFileAsync(fileName, _collection.ToArray());
                MessageBox.Show("保存成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }



        private void gdViewer1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            gdViewer1.ZoomMode = ViewerZoomMode.ZoomModeFitToViewer;
        }

        private void FormExport_FormClosing(object sender, FormClosingEventArgs e)
        {
            //layoutControl1.SaveLayoutToRegistry(_layoutSavePath);
        }

        private void simpleButton1_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 50; i++)
            {
                _collection.Add(new Record());
            }
        }

        private void gridView1_TopRowChanged(object sender, EventArgs e)
        {
            var info = (GridViewInfo)gridView1.GetViewInfo();
            var index = info.RowsInfo.GetLastVisibleRowIndex();

            var lastRowVisible = gridView1.GetRowHandle(gridView1.RowCount - 1) == gridView1.GetRowHandle(index);
            System.Diagnostics.Debug.WriteLine(lastRowVisible);

            if (lastRowVisible && HasNextPage())
            {
                LoadNextPage();
            }

        }

        private void LoadNextPage()
        {
            if (HasNextPage())
            {
                _page.CurrentPage++;
                var list = (_page as IListSource).GetList();
                foreach (TogVehmon vehmon in list)
                {
                    var r = Vehmon2Record(vehmon);
                    _collection.Add(r);
                }
            }

            UpdatePageIndicator();
        }

        private bool HasNextPage()
        {
            return _page != null && _collection != null && _page.CurrentPage < _page.PageCount - 1;
        }

        private void UpdatePageIndicator()
        {
            this.simpleButtonLoadNextPage.Enabled = HasNextPage();

            if (_page != null)
            {
                simpleButtonLoadNextPage.Text = string.Format("已载入 {0}/{1} 页, 单击载入下一页", _page.CurrentPage + 1,
                                                              _page.PageCount);
            }
        }

        private void simpleButtonLoadNextPage_Click(object sender, EventArgs e)
        {
            LoadNextPage();
        }

        private void barButtonItemExportOriginalPictures_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (!IsDateRangeValid())
            {
                return;
            }

            ExportDataAsyncCore(false, ExportPicturesAsync);
        }

    }

    class ExportDataProgress
    {
        public string Text { get; set; }
        public int Percentage { get; set; }
    }

}